home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsio / fsioStream.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  36.7 KB  |  1,127 lines

  1. /* 
  2.  * fsioStream.c --
  3.  *
  4.  *    There are two sets of procedures here.  The first manage the stream
  5.  *    as it relates to the handle table; streams are installed in this
  6.  *    table so that handle synchronization primitives can be used, and
  7.  *    so that streams can be found after migration.  The golden rule is
  8.  *    that the stream's refCount reflects local use, and its client list
  9.  *    is used to reflect remote use of a stream.  Thus I/O server's
  10.  *    don't keep references, only client list entries, unless there is
  11.  *    a local user.
  12.  *
  13.  *    The second set of procedures handle the mapping from streams to
  14.  *    user-level stream IDs,    which are indexes into a per-process array
  15.  *    of stream pointers.
  16.  *
  17.  * Copyright (C) 1987 Regents of the University of California
  18.  * All rights reserved.
  19.  * Permission to use, copy, modify, and distribute this
  20.  * software and its documentation for any purpose and without
  21.  * fee is hereby granted, provided that the above copyright
  22.  * notice appear in all copies.  The University of California
  23.  * makes no representations about the suitability of this
  24.  * software for any purpose.  It is provided "as is" without
  25.  * express or implied warranty.
  26.  */
  27.  
  28. #ifndef lint
  29. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsio/fsioStream.c,v 9.21 92/10/28 18:31:39 mgbaker Exp $ SPRITE (Berkeley)";
  30. #endif not lint
  31.  
  32.  
  33. #include <sprite.h>
  34. #include <fs.h>
  35. #include <fsutil.h>
  36. #include <fsio.h>
  37. #include <fsNameOps.h>
  38. #include <fsconsist.h>
  39. #include <fsStat.h>
  40. #include <fsrmt.h>
  41. #include <proc.h>
  42. #include <procMigrate.h>
  43. #include <sync.h>
  44. #include <rpc.h>
  45. #include <fsioRpc.h>
  46. #include <stdio.h>
  47. #include <fsrecov.h>
  48. #include <recov.h>
  49. #include <fsioStreamInt.h>
  50.  
  51. /*
  52.  * Monitor to synchronize access to the streamCount variable.
  53.  */
  54. static    Sync_Lock    streamLock = Sync_LockInitStatic("Fs:streamLock");
  55. #define LOCKPTR (&streamLock)
  56.  
  57. static int    streamCount;    /* Used to generate fileIDs for streams*/
  58.  
  59. /*
  60.  * Forward declarations. 
  61.  */
  62. static ReturnStatus StreamMigCallback _ARGS_((Fsio_MigInfo *migInfoPtr, 
  63.             Boolean *sharedPtr, int *offsetPtr));
  64.  
  65.  
  66. /*
  67.  *----------------------------------------------------------------------
  68.  *
  69.  * Fsio_StreamCreate --
  70.  *
  71.  *    Create a new stream for a client.  This chooses a unique minor number
  72.  *    for the    fileID of the stream, installs it in the handle table,
  73.  *    and initializes the client list to contain the client.  This is
  74.  *    used on the file server to remember clients of regular files, and
  75.  *    when creating pipe streams which need client info for migration.
  76.  *
  77.  * Results:
  78.  *    A pointer to a locked stream with 1 reference and one client entry.
  79.  *
  80.  * Side effects:
  81.  *    Install the new stream into the handle table and increment the global
  82.  *    streamCount used to generate IDs.  The stream is returned locked and
  83.  *    with one reference.  Our caller should release this reference if
  84.  *    this is just a shadow stream.
  85.  *
  86.  *----------------------------------------------------------------------
  87.  */
  88. ENTRY Fs_Stream *
  89. Fsio_StreamCreate(serverID, clientID, ioHandlePtr, useFlags, name)
  90.     int            serverID;    /* I/O server for stream */
  91.     int            clientID;    /* Client of the stream */
  92.     Fs_HandleHeader    *ioHandlePtr;    /* I/O handle to attach to stream */
  93.     int            useFlags;    /* Usage flags from Fs_Open call */
  94.     char        *name;        /* Name for error messages */
  95. {
  96.     register Boolean found;
  97.     register Fs_Stream *streamPtr;
  98.     Fs_Stream *newStreamPtr;
  99.     Fs_FileID fileID;
  100.  
  101.     LOCK_MONITOR;
  102.  
  103.     /*
  104.      * The streamID is uniquified by using our own host ID for the major
  105.      * field (for network uniqueness), and then choosing minor
  106.      * numbers until we don't have a local conflict.
  107.      */
  108.     fileID.type = FSIO_STREAM;
  109.     fileID.serverID = serverID;
  110.     fileID.major = rpc_SpriteID;
  111.  
  112.     do {
  113.     fileID.minor = ++streamCount;
  114.     found = Fsutil_HandleInstall(&fileID, sizeof(Fs_Stream), name,
  115.                 FALSE, (Fs_HandleHeader **)&newStreamPtr);
  116.     if (found) {
  117.         /*
  118.          * Don't want to conflict with existing streams.
  119.          */
  120.         Fsutil_HandleRelease(newStreamPtr, TRUE);
  121.     }
  122.     } while (found);
  123.  
  124.     streamPtr = newStreamPtr;
  125.     streamPtr->offset = 0;
  126.     streamPtr->flags = useFlags;
  127.     streamPtr->ioHandlePtr = ioHandlePtr;
  128.     streamPtr->nameInfoPtr = (Fs_NameInfo *)NIL;
  129.     List_Init(&streamPtr->clientList);
  130.     fs_Stats.object.streams++;
  131.  
  132.     (void)Fsio_StreamClientOpen(&streamPtr->clientList, clientID, useFlags,
  133.         (Boolean *)NIL);
  134.  
  135.     UNLOCK_MONITOR;
  136.     return(streamPtr);
  137. }
  138.  
  139. /*
  140.  *----------------------------------------------------------------------
  141.  *
  142.  * Fsio_StreamAddClient --
  143.  *
  144.  *    Find a stream and add another client to its client list.
  145.  *
  146.  * Results:
  147.  *    A pointer to a locked stream with 1 reference and one or more 
  148.  *    client entries.  Our call should release this reference if 
  149.  *    this is just a shadow stream.
  150.  *
  151.  * Side effects:
  152.  *    Install the stream into the handle table if it's not there 
  153.  *    already.
  154.  *
  155.  *----------------------------------------------------------------------
  156.  */
  157. Fs_Stream *
  158. Fsio_StreamAddClient(streamIDPtr, clientID, ioHandlePtr, useFlags, name,
  159.         foundClientPtr, foundStreamPtr)
  160.     Fs_FileID        *streamIDPtr;    /* File ID for stream */
  161.     int            clientID;    /* Client of the stream */
  162.     Fs_HandleHeader    *ioHandlePtr;    /* I/O handle to attach to stream */
  163.     int            useFlags;    /* Usage flags from Fs_Open call */
  164.     char        *name;        /* Name for error messages */
  165.     /*
  166.      * These two boolean pointers may be NIL if their info is not needed.
  167.      */
  168.     Boolean        *foundClientPtr;/* True if Client already existed */
  169.     Boolean        *foundStreamPtr;/* True if stream already existed */
  170. {
  171.     register Boolean found;
  172.     register Fs_Stream *streamPtr;
  173.     Fs_Stream *newStreamPtr;
  174.  
  175.     found = Fsutil_HandleInstall(streamIDPtr, sizeof(Fs_Stream), name,
  176.                 FALSE, (Fs_HandleHeader **)&newStreamPtr);
  177.     streamPtr = newStreamPtr;
  178.     if (!found) {
  179.     streamPtr->offset = 0;
  180.     streamPtr->flags = useFlags;
  181.     streamPtr->ioHandlePtr = ioHandlePtr;
  182.     streamPtr->nameInfoPtr = (Fs_NameInfo *)NIL;
  183.     List_Init(&streamPtr->clientList);
  184.     fs_Stats.object.streams++;
  185.     } else if (streamPtr->ioHandlePtr == (Fs_HandleHeader *)NIL) {
  186.     streamPtr->ioHandlePtr = ioHandlePtr;
  187.     }
  188.     (void)Fsio_StreamClientOpen(&streamPtr->clientList, clientID, useFlags,
  189.         foundClientPtr);
  190.     if (foundStreamPtr != (Boolean *)NIL) {
  191.     *foundStreamPtr = found;
  192.     }
  193.  
  194.     return(streamPtr);
  195. }
  196.  
  197. /*
  198.  *----------------------------------------------------------------------
  199.  *
  200.  * Fsio_StreamMigClient --
  201.  *
  202.  *    This is called on the I/O server for to move client streams refs.
  203.  *    This makes a callback to the source client to release the reference
  204.  *    to the stream which has (now) moved away.
  205.  *    Note:  this operation locks the stream in order to serialize
  206.  *    with a close comming in from a remote client who has dup'ed the
  207.  *    stream, migrated one reference, and closed the other reference.
  208.  *    Also, on the client the callback and the regular close will both
  209.  *    try to lock the stream in order to release a reference.  Deadlock
  210.  *    cannot occur because if the close happens first there will be two
  211.  *    references at the client.  The close at the client will release
  212.  *    one reference and not try to contact us.  If the callback occurs
  213.  *    first then the close will come through to us, but it will have
  214.  *    to wait until we are done with this migration.
  215.  *
  216.  * Results:
  217.  *    TRUE if the stream is shared across the network after migration.
  218.  *
  219.  * Side effects:
  220.  *    Shifts the client list entry from one host to another.  This does
  221.  *    not add/subtract any references to the stream here on this host.
  222.  *    However, the call-back releases a reference at the source client.
  223.  *
  224.  *----------------------------------------------------------------------
  225.  */
  226. ENTRY void
  227. Fsio_StreamMigClient(migInfoPtr, dstClientID, ioHandlePtr, closeSrcClientPtr)
  228.     Fsio_MigInfo        *migInfoPtr;    /* Encapsulated stream */
  229.     int            dstClientID;    /* New client of the stream */
  230.     Fs_HandleHeader    *ioHandlePtr;    /* I/O handle to attach to stream */
  231.     Boolean        *closeSrcClientPtr;    /* Return - TRUE if the src
  232.                      * client stopped using stream */
  233. {
  234.     register Boolean found;
  235.     register Fs_Stream *streamPtr;
  236.     Fs_Stream *newStreamPtr;
  237.     int newClientStream = migInfoPtr->flags & FS_NEW_STREAM;
  238.     ReturnStatus status;
  239.     Boolean shared;
  240.     int offset;
  241.  
  242.     /*
  243.      * Get the stream and synchronize with closes from the client.
  244.      * The I/O handle has to be unlocked while the stream is locked
  245.      * in order to prevent deadlock with un-related open/close activity.
  246.      */
  247.     Fsutil_HandleUnlock(ioHandlePtr);
  248.     found = Fsutil_HandleInstall(&migInfoPtr->streamID, sizeof(Fs_Stream),
  249.              (char *)NIL, FALSE, (Fs_HandleHeader **)&newStreamPtr);
  250.     streamPtr = newStreamPtr;
  251.     if (!found) {
  252.     streamPtr->offset = migInfoPtr->offset;
  253.     streamPtr->flags = migInfoPtr->flags & ~FS_NEW_STREAM;
  254.     streamPtr->ioHandlePtr = ioHandlePtr;
  255.     streamPtr->nameInfoPtr = (Fs_NameInfo *)NIL;
  256.     List_Init(&streamPtr->clientList);
  257.     fs_Stats.object.streams++;
  258.     } else if (streamPtr->ioHandlePtr == (Fs_HandleHeader *)NIL) {
  259.     streamPtr->ioHandlePtr = ioHandlePtr;
  260.     }
  261.     if (migInfoPtr->srcClientID != rpc_SpriteID) {
  262.     /*
  263.      * Call back to the client to tell it to release its reference
  264.      * on the stream.  We can't hold the I/O handle locked because
  265.      * an unrelated close from the source client might have the
  266.      * I/O handle locked over there.  By unlocking this I/O handle
  267.      * we allow unrelated closes to complete, while the stream
  268.      * lock prevents closes of other references to this stream
  269.      * from coming in and changing the state.
  270.      */
  271.     status = StreamMigCallback(migInfoPtr, &shared, &offset);
  272.     if ((streamPtr->flags & FS_RMT_SHARED) == 0) {
  273.         /*
  274.          * We don't think the stream is being shared so we
  275.          * grab the offset from the client.
  276.          */
  277.         streamPtr->offset = offset;
  278.         /* XXX Record new offset? */
  279.     }
  280.     } else {
  281.     /*
  282.      * The stream has been migrated away from us, the I/O server.
  283.      * Decrement the stream ref count.  The I/O handle references
  284.      * are left alone here on the I/O server.
  285.      */
  286.     Fsutil_HandleDecRefCount((Fs_HandleHeader *)streamPtr);
  287.     /* XXX Ignore this since we don't include our own streams in box? */
  288.     shared = (streamPtr->hdr.refCount > 1);
  289.     status = SUCCESS;
  290.     }
  291.  
  292.     if (status != SUCCESS || !shared) {
  293.     /*
  294.      * The client doesn't perceive sharing of the stream so
  295.      * it must be its last reference so we indicate an I/O close is needed.
  296.      */
  297.     *closeSrcClientPtr = TRUE;
  298.     (void)Fsio_StreamClientClose(&streamPtr->clientList,
  299.                   migInfoPtr->srcClientID);
  300.     /* Remove from recov box if the ioHandle is of right type too. */
  301.     if (recov_Transparent && migInfoPtr->srcClientID != rpc_SpriteID &&
  302.         Fsrecov_ThisType((Fs_HandleHeader *) ioHandlePtr,
  303.         migInfoPtr->srcClientID) &&
  304.         Fsrecov_DeleteHandle((Fs_HandleHeader *) streamPtr,
  305.         migInfoPtr->srcClientID, streamPtr->flags) != SUCCESS) {
  306.         /* We'll have to do better than this! */
  307.         panic(
  308.         "Fsio_StreamMigClient: couldn't remove handle from recov box.");
  309.     }
  310.     } else {
  311.     *closeSrcClientPtr = FALSE;
  312.     }
  313.     /*
  314.      * Mark (unmark) the stream if it is being shared.  This is checked
  315.      * in the read and write RPC stubs in order to know what offset to use,
  316.      * the one here in the shadow stream, or the one from the client.
  317.      */
  318.     if (Fsio_StreamClientOpen(&streamPtr->clientList, dstClientID,
  319.                 migInfoPtr->flags, (Boolean *)NIL)) {
  320.     streamPtr->flags |= FS_RMT_SHARED;
  321.     } else {
  322.     streamPtr->flags &= ~FS_RMT_SHARED;
  323.     }
  324.     /* Add handle to recov box if it's of right type. */
  325.     if (recov_Transparent && ioHandlePtr != (Fs_HandleHeader *) NIL &&
  326.         dstClientID != rpc_SpriteID
  327.         && Fsrecov_ThisType((Fs_HandleHeader *) ioHandlePtr, dstClientID)) {
  328.     status = Fsrecov_AddHandle((Fs_HandleHeader *) streamPtr,
  329.         &(ioHandlePtr->fileID), dstClientID, streamPtr->flags,
  330.         streamPtr->offset, TRUE);
  331.     } else if (ioHandlePtr == (Fs_HandleHeader *) NIL) {
  332.     panic("Fsio_StreamMigClient: ioHandlePtr was NIL");
  333.     }
  334.     /* We'll have to do better than this! */
  335.     if (recov_Transparent && status != SUCCESS) {
  336.     panic("Fsio_StreamMigClient: couldn't add handle to recov box.");
  337.     }
  338.     migInfoPtr->flags = streamPtr->flags | newClientStream;
  339.     migInfoPtr->offset = streamPtr->offset;
  340.     Fsutil_HandleRelease(streamPtr, TRUE);
  341.     Fsutil_HandleLock(ioHandlePtr);
  342. }
  343.  
  344. /*
  345.  * Parameters and results for RPC_FS_RELEASE that is called
  346.  * to release a reference to a stream on the source of a migration.
  347.  */
  348. typedef struct {
  349.     Fs_FileID streamID;        /* Stream from which to release a reference */
  350. } FsStreamReleaseParam;
  351.  
  352. typedef struct {
  353.     Boolean    inUse;        /* TRUE if stream still in use after release */
  354.     int        offset;        /* Offset of stream on source of migration. */
  355. } FsStreamReleaseReplyNew;
  356.  
  357. /*
  358.  *----------------------------------------------------------------------
  359.  *
  360.  * StreamMigCallback --
  361.  *
  362.  *    Call back to the source client of a migration and tell it to
  363.  *    release its stream.  This invokes Fsio_StreamMigrate on the
  364.  *    remote client
  365.  *
  366.  * Results:
  367.  *    A return status.
  368.  *
  369.  * Side effects:
  370.  *      None.
  371.  *    
  372.  *----------------------------------------------------------------------
  373.  */
  374. static ReturnStatus
  375. StreamMigCallback(migInfoPtr, sharedPtr, offsetPtr)
  376.     Fsio_MigInfo    *migInfoPtr;    /* Encapsulated information */
  377.     Boolean    *sharedPtr;    /* TRUE if stream still used on client */
  378.     int     *offsetPtr;    /* Offset of stream on client */
  379. {
  380.     register ReturnStatus    status;
  381.     Rpc_Storage         storage;
  382.     FsStreamReleaseParam    param;
  383.     FsStreamReleaseReplyNew    replyNew;
  384.  
  385.     param.streamID = migInfoPtr->streamID;
  386.     storage.requestParamPtr = (Address) ¶m;
  387.     storage.requestParamSize = sizeof(param);
  388.     storage.requestDataPtr = (Address)NIL;
  389.     storage.requestDataSize = 0;
  390.  
  391.     replyNew.inUse = FALSE;
  392.     storage.replyParamPtr = (Address)&replyNew;
  393.     storage.replyParamSize = sizeof(replyNew);
  394.     storage.replyDataPtr = (Address) NIL;
  395.     storage.replyDataSize = 0;
  396.  
  397.     status = Rpc_Call(migInfoPtr->srcClientID, RPC_FS_RELEASE_NEW, &storage);
  398.     *sharedPtr = replyNew.inUse;
  399.     *offsetPtr = replyNew.offset;
  400. #ifdef NOTDEF
  401.     if (status != SUCCESS && fsio_MigDebug) {
  402.     printf("StreamMigCallback: status %x from RPC.\n", status);
  403.     }
  404. #endif
  405.     return(status);
  406. }
  407.  
  408.  
  409. /*
  410.  *----------------------------------------------------------------------
  411.  *
  412.  * Fsio_RpcStreamMigCloseNew --
  413.  *
  414.  *    The service stub for FsStreamMigCallback.
  415.  *    This invokes the StreamMigrate routine that releases a reference
  416.  *    to a stream on this host.  Our reply message indicates if
  417.  *    the stream is still in use on this host, and what its offset is.
  418.  *
  419.  * Results:
  420.  *    FS_STALE_HANDLE if handle that if client that is migrating the file
  421.  *    doesn't have the file opened on this machine.  Otherwise return
  422.  *    SUCCESS.  
  423.  *
  424.  * Side effects:
  425.  *    None.
  426.  *
  427.  *----------------------------------------------------------------------
  428.  */
  429. /*ARGSUSED*/
  430. ReturnStatus
  431. Fsio_RpcStreamMigCloseNew(srvToken, clientID, command, storagePtr)
  432.     ClientData srvToken;    /* Handle on server process passed to
  433.                  * Rpc_Reply */
  434.     int clientID;        /* Sprite ID of client host */
  435.     int command;        /* Command identifier */
  436.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  437.                  * buffers and also indicate the exact amount
  438.                  * of data in the request buffers.  The reply
  439.                  * fields are initialized to NIL for the
  440.                  * pointers and 0 for the lengths.  This can
  441.                  * be passed to Rpc_Reply */
  442. {
  443.     register FsStreamReleaseParam    *paramPtr;
  444.     register Fs_Stream            *streamPtr;
  445.     register ReturnStatus        status;
  446.     register FsStreamReleaseReplyNew    *replyPtr;
  447.     register Rpc_ReplyMem        *replyMemPtr;
  448.  
  449.     paramPtr = (FsStreamReleaseParam *) storagePtr->requestParamPtr;
  450.  
  451.     streamPtr = Fsio_StreamClientVerify(¶mPtr->streamID,
  452.                 (Fs_HandleHeader *)NIL, rpc_SpriteID);
  453.     if (streamPtr == (Fs_Stream *) NIL) {
  454.     printf("Fsio_RpcStreamMigCloseNew, unknown stream <%d>, client %d\n",
  455.         paramPtr->streamID.minor, clientID);
  456.     return( (paramPtr->streamID.minor < 0) ? GEN_INVALID_ARG
  457.                            : FS_STALE_HANDLE);
  458.     }
  459.     replyPtr = mnew(FsStreamReleaseReplyNew);
  460.     storagePtr->replyParamPtr = (Address)replyPtr;
  461.     storagePtr->replyParamSize = sizeof(FsStreamReleaseReplyNew);
  462.     storagePtr->replyDataPtr = (Address)NIL;
  463.     storagePtr->replyDataSize = 0;
  464.  
  465.     status = Fsio_StreamMigCloseNew(streamPtr, &replyPtr->inUse,
  466.                     &replyPtr->offset);
  467.  
  468.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  469.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  470.     replyMemPtr->dataPtr = (Address) NIL;
  471.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  472.         (ClientData)replyMemPtr);
  473.     return(SUCCESS);
  474. }
  475.  
  476. /*
  477.  * ----------------------------------------------------------------------------
  478.  *
  479.  * Fsio_StreamMigCloseNew --
  480.  *
  481.  *    This is called to release a reference to a stream at the source
  482.  *    of a migration.  We are told to release the reference by the
  483.  *    I/O server during its Fsio_StreamMigClient call.  The timing of our
  484.  *    call ensures that a simultaneous Fs_Close on the stream will be
  485.  *    properly synchronized - the I/O server has to know how many
  486.  *    stream references we, the source of a migration, really have.  It also
  487.  *    keeps the offset consistent in the face of operations after
  488.  *    encapsulation.
  489.  *
  490.  * Results:
  491.  *    SUCCESS unless the stream isn't even found.  This sets *inUsePtr
  492.  *    if the stream is still in use here, otherwise it clears this flag.
  493.  *    This also sets *offsetPtr to the current offset of the stream.
  494.  *
  495.  * Side effects:
  496.  *    This releases one reference to the stream.  If it is the last
  497.  *    reference then this propogates the close down to the I/O handle
  498.  *    by calling the stream-specific release procedure.
  499.  *
  500.  * ----------------------------------------------------------------------------
  501.  *
  502.  */
  503. /*ARGSUSED*/
  504. ReturnStatus
  505. Fsio_StreamMigCloseNew(streamPtr, inUsePtr, offsetPtr)
  506.     Fs_Stream *streamPtr;    /* Stream to release, should be locked */
  507.     Boolean *inUsePtr;        /* TRUE if still in use after release */
  508.     int *offsetPtr;        /* Current stream offset */
  509. {
  510.     /*
  511.      * Set the offset we are passing back to the I/O server.
  512.      */
  513.     *offsetPtr = streamPtr->offset;
  514.     /*
  515.      * Release the reference that has now migrated away.
  516.      */
  517.     Fsutil_HandleDecRefCount((Fs_HandleHeader *)streamPtr);
  518.     /*
  519.      * If this is the last reference then call down to the I/O handle
  520.      * so it can decrement use counts that come from the stream.
  521.      * (Remember there is still one reference from Fsio_RpcStreamMigCloseNew)
  522.      */
  523.     if (streamPtr->hdr.refCount <= 1) {
  524.     (*fsio_StreamOpTable[streamPtr->ioHandlePtr->fileID.type].release)
  525.         (streamPtr->ioHandlePtr, streamPtr->flags);
  526.     /* XXX This is on client here, what should I do about recov box? */
  527.     if (Fsio_StreamClientClose(&streamPtr->clientList, rpc_SpriteID)) {
  528.         /*
  529.          * No references, no other clients, nuke it.
  530.          */
  531.         *inUsePtr = FALSE;
  532.         Fsio_StreamDestroy(streamPtr);
  533.         return(SUCCESS);
  534.     }
  535.     }
  536.     *inUsePtr = TRUE;
  537.     streamPtr->flags |= FS_RMT_SHARED;
  538.     Fsutil_HandleRelease(streamPtr, TRUE);
  539.     return(SUCCESS);
  540. }
  541.  
  542. /*
  543.  *----------------------------------------------------------------------
  544.  *
  545.  * Fsio_StreamCreateID --
  546.  *
  547.  *    Generate a new streamID for a client.  This chooses a unique minor
  548.  *    number for the    fileID of the stream and returns the fileID.  This
  549.  *    is used on the file server to generate IDs for remote device streams.
  550.  *    This ID will be used to create matching streams on the device I/O server
  551.  *    and on the client's machine.
  552.  *
  553.  * Results:
  554.  *    A unique fileID for a stream to the given I/O server.
  555.  *
  556.  * Side effects:
  557.  *    Increment the global streamCount used to generate IDs.
  558.  *
  559.  *----------------------------------------------------------------------
  560.  */
  561. ENTRY void
  562. Fsio_StreamCreateID(serverID, streamIDPtr)
  563.     int            serverID;    /* I/O server for stream */
  564.     Fs_FileID        *streamIDPtr;    /* Return - FileID for the stream */
  565. {
  566.     register Boolean found;
  567.     Fs_Stream *newStreamPtr;
  568.     Fs_FileID fileID;
  569.  
  570.     LOCK_MONITOR;
  571.  
  572.     /*
  573.      * The streamID is uniquified by using our own host ID for the major
  574.      * field (for network uniqueness), and then choosing minor
  575.      * numbers until we don't have a local conflict.
  576.      */
  577.     fileID.type = FSIO_STREAM;
  578.     fileID.serverID = serverID;
  579.     fileID.major = rpc_SpriteID;
  580.  
  581.     do {
  582.     fileID.minor = ++streamCount;
  583.     found = Fsutil_HandleInstall(&fileID, sizeof(Fs_Stream), (char *)NIL,
  584.                 FALSE, (Fs_HandleHeader **)&newStreamPtr);
  585.     if (found) {
  586.         /*
  587.          * Don't want to conflict with existing streams.
  588.          */
  589.         Fsutil_HandleRelease(newStreamPtr, TRUE);
  590.     }
  591.     } while (found);
  592.     *streamIDPtr = newStreamPtr->hdr.fileID;
  593.     Fsutil_HandleRelease(newStreamPtr, TRUE);
  594.     Fsutil_HandleRemove(newStreamPtr);
  595.     UNLOCK_MONITOR;
  596. }
  597.  
  598. /*
  599.  *----------------------------------------------------------------------
  600.  *
  601.  * Fsio_StreamCopy --
  602.  *
  603.  *    Duplicate a stream.  This ups the reference count on the stream
  604.  *    so that it won't go away until its last user closes it.
  605.  *
  606.  * Results:
  607.  *    None.
  608.  *
  609.  * Side effects:
  610.  *    The reference count on the stream is incremented.
  611.  *
  612.  *----------------------------------------------------------------------
  613.  */
  614. ENTRY void
  615. Fsio_StreamCopy(oldStreamPtr, newStreamPtrPtr)
  616.     Fs_Stream *oldStreamPtr;
  617.     Fs_Stream **newStreamPtrPtr;
  618. {
  619.     *newStreamPtrPtr = Fsutil_HandleDupType(Fs_Stream, oldStreamPtr);
  620.     Fsutil_HandleUnlock(oldStreamPtr);
  621. }
  622.  
  623. /*
  624.  *----------------------------------------------------------------------
  625.  *
  626.  * Fsio_StreamClientVerify --
  627.  *
  628.  *    Verify that the remote client is known for the stream, and return
  629.  *    a locked pointer to the stream's handle.
  630.  *
  631.  * Results:
  632.  *    A pointer to the handle for the stream, or NIL if
  633.  *    the client is bad.
  634.  *
  635.  * Side effects:
  636.  *    The handle is returned locked and with its refCount incremented.
  637.  *    It should be released with Fsutil_HandleRelease(..., TRUE)
  638.  *
  639.  *----------------------------------------------------------------------
  640.  */
  641.  
  642. Fs_Stream *
  643. Fsio_StreamClientVerify(streamIDPtr, ioHandlePtr, clientID)
  644.     Fs_FileID    *streamIDPtr;        /* Client's stream ID */
  645.     Fs_HandleHeader *ioHandlePtr;    /* I/O handle the client thinks
  646.                      * is attached to the stream */
  647.     int        clientID;        /* Host ID of the client */
  648. {
  649.     register FsioStreamClient *clientPtr;
  650.     register Fs_Stream *streamPtr;
  651.     Boolean found = FALSE;
  652.  
  653.     streamPtr = Fsutil_HandleFetchType(Fs_Stream, streamIDPtr);
  654.     if (streamPtr != (Fs_Stream *)NIL) {
  655.     LIST_FORALL(&streamPtr->clientList, (List_Links *) clientPtr) {
  656.         if (clientPtr->clientID == clientID) {
  657.         found = TRUE;
  658.         break;
  659.         }
  660.     }
  661.     if (!found) {
  662.         printf("Fsio_StreamClientVerify: no client %d for stream <%d> \"%s\"\n",
  663.         clientID, streamPtr->hdr.fileID.minor,
  664.         Fsutil_HandleName((Fs_HandleHeader *)streamPtr));
  665.         Fsutil_HandleRelease(streamPtr, TRUE);
  666.         streamPtr = (Fs_Stream *)NIL;
  667.  
  668.     } else if (ioHandlePtr != (Fs_HandleHeader *)NIL &&
  669.            streamPtr->ioHandlePtr != ioHandlePtr) {
  670.         /*
  671.          * The client's stream doesn't reference the same handle as we do.
  672.          * Note that ioHandlePtr is NIL when we are called from
  673.          * Fsio_RpcStreamMigCloseNew, so we can't make this check in that case.
  674.          */
  675.         printf("Fsio_StreamClientVerify ioHandle mismatch client ID %d:\n",
  676.             clientID);
  677.         if (streamPtr->ioHandlePtr == (Fs_HandleHeader *)NIL) {
  678.         printf("\tStream <%d> \"%s\" my I/O handle NIL\n",
  679.             Fsutil_HandleName(streamPtr), streamIDPtr->minor);
  680.         } else {
  681.         printf("\tStream <%d> my handle %s \"%s\" <%d,%d>\n",
  682.             streamIDPtr->minor,
  683.             Fsutil_FileTypeToString(streamPtr->ioHandlePtr->fileID.type),
  684.             Fsutil_HandleName(streamPtr->ioHandlePtr),
  685.             streamPtr->ioHandlePtr->fileID.major,
  686.             streamPtr->ioHandlePtr->fileID.minor);
  687.         }
  688.         printf("\tClient %d handle %s \"%s\" <%d,%d>\n",
  689.             clientID, Fsutil_HandleName(ioHandlePtr),
  690.             Fsutil_FileTypeToString(ioHandlePtr->fileID.type),
  691.             ioHandlePtr->fileID.major, ioHandlePtr->fileID.minor);
  692.        Fsutil_HandleRelease(streamPtr, TRUE);
  693.        streamPtr = (Fs_Stream *)NIL;
  694.     }
  695.     } else {
  696.     printf("No stream <%d> for client %d\n", streamIDPtr->minor, clientID);
  697.     }
  698.     return(streamPtr);
  699. }
  700.  
  701.  
  702. /*
  703.  *----------------------------------------------------------------------
  704.  *
  705.  * Fsio_StreamClientKill --
  706.  *
  707.  *    Called when a client is assumed down.  This cleans up the
  708.  *    client list for the stream or removes the stream.
  709.  *
  710.  * Results:
  711.  *    None.
  712.  *
  713.  * Side effects:
  714.  *    Removes the client list entry for the client.
  715.  *    It removes or unlocks the handle.
  716.  *
  717.  *----------------------------------------------------------------------
  718.  */
  719. void
  720. Fsio_StreamClientKill(hdrPtr, clientID)
  721.     Fs_HandleHeader    *hdrPtr;    /* Stream to clean up */
  722.     int            clientID;    /* Host assumed down */
  723. {
  724.     Fs_Stream        *streamPtr = (Fs_Stream *) hdrPtr;
  725.  
  726.     if (!Fsio_StreamClientClose(&streamPtr->clientList, clientID)) {
  727.     /*
  728.      * There were other clients.
  729.      */
  730.     Fsutil_HandleUnlock(streamPtr);
  731.     } else {
  732.     Fsutil_HandleRemove(streamPtr);
  733.     }
  734. }
  735.  
  736.  
  737. /*
  738.  *----------------------------------------------------------------------
  739.  *
  740.  * Fsio_StreamDestroy --
  741.  *
  742.  *    Discard a stream.  This call removes the stream from the handle
  743.  *    table and frees associated storage.  The I/O handle pointer part
  744.  *    should have already been cleaned up by its handler.
  745.  *
  746.  *    If the stream still has associated clients, release the reference
  747.  *    to the stream but don't get rid of the stream, since it is a shadow
  748.  *    stream.
  749.  *
  750.  * Results:
  751.  *    None.
  752.  *
  753.  * Side effects:
  754.  *    Remove the stream handle from the handle table.
  755.  *
  756.  *----------------------------------------------------------------------
  757.  */
  758.  
  759. Boolean fsio_StreamDisposeDebug = TRUE;
  760.  
  761. ENTRY void
  762. Fsio_StreamDestroy(streamPtr)
  763.     register Fs_Stream *streamPtr;
  764. {
  765.     Boolean noClients = TRUE;
  766.     
  767.     if (!List_IsEmpty(&streamPtr->clientList)) {
  768.     noClients = FALSE;
  769.     if (fsio_StreamDisposeDebug) {
  770.         register FsioStreamClient *clientPtr;
  771.  
  772.         LIST_FORALL(&streamPtr->clientList, (List_Links *) clientPtr) {
  773.  
  774.         printf("Fsio_StreamDestroy, client %d still in list for stream <%d,%d>, refCount %d\n",
  775.               clientPtr->clientID, streamPtr->hdr.fileID.major,
  776.               streamPtr->hdr.fileID.minor, streamPtr->hdr.refCount);
  777.         if (streamPtr->ioHandlePtr != (Fs_HandleHeader *)NIL) {
  778.             printf("\tI/O handle: %s <%d,%d>, refCount %d\n",
  779.                    Fsutil_FileTypeToString(streamPtr->ioHandlePtr->fileID.type),
  780.                    streamPtr->ioHandlePtr->fileID.major,
  781.                    streamPtr->ioHandlePtr->fileID.minor,
  782.                    streamPtr->ioHandlePtr->refCount);
  783.         }
  784.         }
  785.     }
  786.     } 
  787.  
  788.     Fsutil_HandleRelease(streamPtr, TRUE);
  789.     if (noClients) {
  790.     if (streamPtr->nameInfoPtr != (Fs_NameInfo *)NIL) {
  791.         free((Address)streamPtr->nameInfoPtr);
  792.     }
  793.     Fsutil_HandleRemove(streamPtr);
  794.     fs_Stats.object.streams--;
  795.     }
  796. }
  797.  
  798. /*
  799.  *----------------------------------------------------------------------
  800.  *
  801.  * Fsio_StreamScavenge --
  802.  *
  803.  *    Scavenge a stream.  Servers may have no references to a stream handle,
  804.  *    but still have some things on its client list.  Clients have
  805.  *    references, but no client list.  A stream with neither references
  806.  *    or a client list is scavengable.
  807.  *
  808.  * Results:
  809.  *    None.
  810.  *
  811.  * Side effects:
  812.  *    Removes the stream handle if it has no references and no clients.
  813.  *
  814.  *----------------------------------------------------------------------
  815.  */
  816. #ifdef notdef
  817. Boolean
  818. Fsio_StreamScavenge(hdrPtr)
  819.     Fs_HandleHeader *hdrPtr;
  820. {
  821.     register Fs_Stream *streamPtr = (Fs_Stream *)hdrPtr;
  822.  
  823.     if (streamPtr->hdr.refCount == 0 &&
  824.     List_IsEmpty(&streamPtr->clientList)) {
  825.     printf( "Fsio_StreamScavenge, removing stream <%d,%d>\n",
  826.         streamPtr->hdr.fileID.serverID,
  827.         streamPtr->hdr.fileID.minor);
  828.     Fsutil_HandleRemove((Fs_HandleHeader *)streamPtr);
  829.     fs_Stats.object.streams--;
  830.     return(TRUE);
  831.     } else {
  832.     Fsutil_HandleUnlock((Fs_HandleHeader *)streamPtr);
  833.     return(FALSE);
  834.     }
  835. }
  836. #endif notdef
  837.  
  838.  
  839. typedef struct StreamReopenParams {
  840.     Fs_FileID    streamID;
  841.     Fs_FileID    ioFileID;
  842.     int        useFlags;
  843.     int        offset;
  844. } StreamReopenParams;
  845.  
  846. /*
  847.  *----------------------------------------------------------------------
  848.  *
  849.  * Fsio_StreamReopen --
  850.  *
  851.  *    This is called initially on the client side from FsHandleReopen.
  852.  *    That instance then does an RPC to the server, which again invokes
  853.  *    this routine.  On the client side we don't do much except pass
  854.  *    over the streamID and the ioHandle fileID so the server can
  855.  *    re-create state.  On the server we have to re-setup the stream,
  856.  *    which is sort of a pain because it must reference the correct
  857.  *    I/O handle.
  858.  *
  859.  * Results:
  860.  *    SUCCESS if the stream was reopened.
  861.  *
  862.  * Side effects:
  863.  *    On the client, do an RPC to the server.
  864.  *    On the server, re-create the stream.
  865.  *
  866.  *----------------------------------------------------------------------
  867.  */
  868. /*ARGSUSED*/
  869. ENTRY ReturnStatus
  870. Fsio_StreamReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  871.     Fs_HandleHeader    *hdrPtr;    /* Stream's handle header */
  872.     int            clientID;
  873.     ClientData        inData;        /* Non-NIL on the server */
  874.     int            *outSizePtr;    /* Unused. */
  875.     ClientData        *outDataPtr;    /* Unused. */
  876. {
  877.     register Fs_Stream    *streamPtr = (Fs_Stream *)hdrPtr;
  878.     ReturnStatus status;
  879.  
  880.     if (inData == (ClientData)NIL) {
  881.     /*
  882.      * Called on the client side.  We contact the server to invoke
  883.      * this procedure there with some input parameters.
  884.      */
  885.     StreamReopenParams reopenParams;
  886.     int outSize = 0;
  887.  
  888.     reopenParams.streamID = hdrPtr->fileID;
  889.     reopenParams.ioFileID = streamPtr->ioHandlePtr->fileID;
  890.     reopenParams.useFlags = streamPtr->flags;
  891.     reopenParams.offset   = streamPtr->offset;
  892.     /*
  893.      * This is a mousetrap to catch the "poison packets" reported in
  894.      * log message 30402.  It can be removed once that bug is fixed.
  895.      * JHH 12/10/90
  896.      */
  897.     if (reopenParams.ioFileID.type == -1) {
  898.         panic("About to reopen stream with ioFileID.type set to -1\n");
  899.     }
  900.     status = FsrmtReopen(hdrPtr, sizeof(reopenParams),
  901.             (Address)&reopenParams, &outSize, (Address)NIL);
  902.     /*
  903.      * This here is the server side fix for the "poison packet" bug.
  904.      * Ignore the request if the type is -1.  Remove this when
  905.      * the bug is fixed.
  906.      * JHH 12/10/90
  907.      */
  908.     } else if (((StreamReopenParams *) inData)->ioFileID.type < 0 ||
  909.         ((StreamReopenParams *) inData)->ioFileID.type >=
  910.         FSIO_NUM_STREAM_TYPES) {
  911.     printf("Fsio_StreamReopen: fileID type = 0x%x from client %d\n",
  912.         ((StreamReopenParams *) inData)->ioFileID.type, clientID);
  913.     status = FAILURE;
  914.     } else {
  915.     /*
  916.      * Called on the server side.  We need to first make sure there
  917.      * is a corresponding I/O handle for the stream, and then we
  918.      * can set up the stream.
  919.      */
  920.     StreamReopenParams    *reopenParamsPtr;
  921.     register Fs_FileID    *fileIDPtr;
  922.     Fs_HandleHeader        *ioHandlePtr;
  923.     /* 
  924.      * Note about shared stream recovery.  We loose the offset of
  925.      * a shared stream during a crash.  We just print a message and
  926.      * try to go forward.  Often the shared stream is for a process's
  927.      * current working directory, so the offset doesn't matter.
  928.      */
  929.     Boolean            patchOffset = FALSE;
  930.  
  931.     reopenParamsPtr = (StreamReopenParams *)inData;
  932.     fileIDPtr = &reopenParamsPtr->ioFileID;
  933.  
  934.     /* If this is a fast restart, we can look at recov box contents. */
  935.     if (recov_Transparent && fsrecov_AlreadyInit) {
  936.         Fs_FileID           streamID;
  937.         Fsrecov_HandleState    recovInfo;
  938.  
  939.         streamID = reopenParamsPtr->streamID;
  940.         printf("Reopen, looking for stream %d.%d.%d.%d\n", streamID.type,
  941.             streamID.serverID, streamID.major, streamID.minor);
  942.         /* Get info from recov box. */
  943.         status = Fsrecov_GetHandle(streamID, clientID, &recovInfo, TRUE);
  944.         if (status != SUCCESS) {
  945.         panic("Fsio_StreamReopen: couldn't get recov info for handle.");
  946.         }
  947.         /* Test it for sameness. */
  948.         if ((recovInfo.fileID.major != streamID.major) ||
  949.             (recovInfo.fileID.minor != streamID.minor)) {
  950.         panic("Fsio_StreamReopen: major or minor numbers disagree.");
  951.         }
  952.         if ((recovInfo.otherID.major != fileIDPtr->major) ||
  953.             (recovInfo.otherID.minor != fileIDPtr->minor)) {
  954.         panic(
  955.         "Fsio_StreamReopen: ioHandle major or minor numbers disagree.");
  956.         }
  957.         if (((unsigned int) recovInfo.info & FS_RMT_SHARED) !=
  958.             (reopenParamsPtr->useFlags & FS_RMT_SHARED)) {
  959.         panic("Fsio_StreamReopen: flags disagree.");
  960.         }
  961.         /*
  962.          * Offsets don't seem to matter on pdev control streams.
  963.          * I assume they only matter if the stream is shared, but
  964.          * how do I detect that here? XXX
  965.          */
  966.         if (recovInfo.otherID.type != FSIO_CONTROL_STREAM &&
  967.             recovInfo.clientData != reopenParamsPtr->offset) {
  968.         panic("Fsio_StreamReopen: offsets disagree.");
  969.         }
  970.         if (fsrecov_FromBox) {
  971.         /* Just use stream info that was recovered from recov box. */
  972.         return SUCCESS;
  973.         }
  974.     }
  975.  
  976.     ioHandlePtr = (*fsio_StreamOpTable[fileIDPtr->type].clientVerify)
  977.             (fileIDPtr, clientID, (int *)NIL);
  978.     if (ioHandlePtr != (Fs_HandleHeader *)NIL) {
  979.         status = SUCCESS;
  980.         streamPtr = Fsutil_HandleFetchType(Fs_Stream,
  981.             &reopenParamsPtr->streamID);
  982.         if (streamPtr != (Fs_Stream *)NIL) {
  983.         /*
  984.          * Verify that we have the stream hooked to the same
  985.          * I/O handle as the client.  It is possible that we
  986.          * have reused the client's stream ID with a different
  987.          * I/O handle, in which case the client loses this stream.
  988.          */
  989.         if (streamPtr->ioHandlePtr != ioHandlePtr) {
  990.             printf("Fsio_StreamReopen, I/O handle mismatch, client %d its I/O <%d,%d> my I/O <%d,%d>\n",
  991.             clientID,
  992.             ioHandlePtr->fileID.major,
  993.             ioHandlePtr->fileID.minor,
  994.             streamPtr->ioHandlePtr->fileID.major,
  995.             streamPtr->ioHandlePtr->fileID.minor);
  996.             status = FAILURE;
  997.         } else if ((reopenParamsPtr->useFlags & FS_RMT_SHARED) &&
  998.                (streamPtr->flags & FS_RMT_SHARED) == 0) {
  999.             /*
  1000.              * The client thinks the stream is shared by processes
  1001.              * on a different client, but we lost the shadow stream.
  1002.              * (If we do think the stream is shared things are ok.)
  1003.              */
  1004.             printf("Fsio_StreamReopen, not a shadow stream, client %d stream <%d> client I/O <%d,%d>\n",
  1005.                 clientID, streamPtr->hdr.fileID.minor,
  1006.                 ioHandlePtr->fileID.major,
  1007.                 ioHandlePtr->fileID.minor);
  1008.             status = FAILURE;
  1009.         }
  1010.         Fsutil_HandleRelease(streamPtr, TRUE);
  1011.         } else if (reopenParamsPtr->useFlags & FS_RMT_SHARED) {
  1012.         /*
  1013.          * The client thinks the stream is shared by processes
  1014.          * on a different client, but we don't have a shadow stream.
  1015.          */
  1016.         printf("Fsio_StreamReopen, lost shared stream offset? using offset (%d), client %d, I/O <%d,%d> \"%s\"\n",
  1017.             reopenParamsPtr->offset, clientID,
  1018.             ioHandlePtr->fileID.major,
  1019.             ioHandlePtr->fileID.minor,
  1020.             Fsutil_HandleName(ioHandlePtr));
  1021.         patchOffset = TRUE;
  1022.         }
  1023.         if (status == SUCCESS) {
  1024.         streamPtr = Fsio_StreamAddClient(&reopenParamsPtr->streamID,
  1025.             clientID, ioHandlePtr, reopenParamsPtr->useFlags,
  1026.             ioHandlePtr->name, (Boolean *)NIL, (Boolean *)NIL);
  1027.         /*
  1028.          * There isn't proper recovery of the offset if the stream
  1029.          * was shared when we crashed, but here we fake it.
  1030.          */
  1031.         if (patchOffset) {
  1032.             streamPtr->offset = reopenParamsPtr->offset;
  1033.         }
  1034.         if (recov_Transparent && status == SUCCESS &&
  1035.             !fsrecov_AlreadyInit) {
  1036.             status = Fsrecov_AddHandle((Fs_HandleHeader *) streamPtr,
  1037.                 (Fs_FileID *) &(ioHandlePtr->fileID), clientID,
  1038.                 streamPtr->flags, streamPtr->offset, TRUE);
  1039.             if (status != SUCCESS) {
  1040.             /* We'll have to do better than this! */
  1041.             panic("Fsio_StreamReopen: couldn't add stream to box.");
  1042.             }
  1043.         }
  1044.         Fsutil_HandleRelease(streamPtr, TRUE);
  1045.         }
  1046.         Fsutil_HandleRelease(ioHandlePtr, TRUE);
  1047.     } else {
  1048.         printf("Fsio_StreamReopen, %s I/O handle <%d,%d> not found\n",
  1049.         Fsutil_FileTypeToString(fileIDPtr->type),
  1050.         fileIDPtr->major, fileIDPtr->minor);
  1051.         status = FAILURE;
  1052.     }
  1053.     }
  1054.     return(status);
  1055. }
  1056.  
  1057. /*
  1058.  *----------------------------------------------------------------------
  1059.  *
  1060.  * FsioSetupStreamReopen --
  1061.  *
  1062.  *    This is called on the client side from FsHandleReopen.
  1063.  *
  1064.  * Results:
  1065.  *    SUCCESS if the stream is setup to be reopened.
  1066.  *
  1067.  * Side effects:
  1068.  *    None.
  1069.  *
  1070.  *----------------------------------------------------------------------
  1071.  */
  1072. ReturnStatus
  1073. FsioSetupStreamReopen(hdrPtr, paramsPtr)
  1074.     Fs_HandleHeader    *hdrPtr;    /* Stream's handle header */
  1075.     Address        paramsPtr;
  1076. {
  1077.     register Fs_Stream    *streamPtr = (Fs_Stream *)hdrPtr;
  1078.     StreamReopenParams    *reopenParamsPtr = (StreamReopenParams *)paramsPtr;
  1079.  
  1080.     /*
  1081.      * Called on the client side.  We contact the server to invoke
  1082.      * this procedure there with some input parameters.
  1083.      */
  1084.  
  1085.     reopenParamsPtr->streamID = hdrPtr->fileID;
  1086.     reopenParamsPtr->ioFileID = streamPtr->ioHandlePtr->fileID;
  1087.     reopenParamsPtr->useFlags = streamPtr->flags;
  1088.     reopenParamsPtr->offset   = streamPtr->offset;
  1089.     /*
  1090.      * This is a mousetrap to catch the "poison packets" reported in
  1091.      * log message 30402.  It can be removed once that bug is fixed.
  1092.      * JHH 12/10/90
  1093.      */
  1094.     if (reopenParamsPtr->ioFileID.type == -1) {
  1095.     panic("About to reopen stream with ioFileID.type set to -1\n");
  1096.     }
  1097.  
  1098.     return SUCCESS;
  1099. }
  1100.  
  1101.  
  1102. /*
  1103.  *----------------------------------------------------------------------
  1104.  *
  1105.  * FsioFinishStreamReopen --
  1106.  *
  1107.  *    This is called on the client side after the bulk reopen.
  1108.  *
  1109.  * Results:
  1110.  *    None.
  1111.  *
  1112.  * Side effects:
  1113.  *    None.
  1114.  *
  1115.  *----------------------------------------------------------------------
  1116.  */
  1117. /*ARGSUSED*/
  1118. void
  1119. FsioFinishStreamReopen(hdrPtr, statePtr, status)
  1120.     Fs_HandleHeader    *hdrPtr;
  1121.     Address        statePtr;
  1122.     ReturnStatus    status;
  1123. {
  1124.     /* Nothing to do for streams. */
  1125.     return;
  1126. }
  1127.